package cn.jinbyte.web.serialize;


import cn.jinbyte.core.handler.crypt.CryptHandler;
import cn.jinbyte.core.helper.SpringContextHelper;
import cn.jinbyte.web.annotation.CryptProp;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;

import java.io.IOException;

/**
 * 密文字段序列化
 *
 * @author jinty
 * @since 1.0.0
 */
@Slf4j
public class CryptPropSerializer extends JsonSerializer<Object> implements ContextualSerializer {

    private CryptProp annotation;

    @Override
    public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (value == null) {
            jsonGenerator.writeObject(null);
            return;
        }
        Class<? extends CryptHandler> cryptHandlerClass = annotation.handler();

        CryptHandler cryptHandler = null;
        try {
            cryptHandler = SpringContextHelper.getBean(cryptHandlerClass);
        } catch (BeansException e) {
            log.error("Not Found CryptHandler: {}", cryptHandlerClass.getName());
        }
        if (cryptHandler == null) {
            jsonGenerator.writeObject(value);
        } else {
            String encode = cryptHandler.encode(value);
            jsonGenerator.writeString(encode);
        }

    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        CryptProp annotation = beanProperty.getAnnotation(CryptProp.class);
        if (annotation != null) {
            this.annotation = annotation;
            return this;
        }
        return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
    }
}
